﻿using Frameworks;
using Networks.Senders;
using Newtonsoft.Json.Linq;
using Pomelo.DotNetClient;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Networks
{
    public class NetworkManager : Singleton<NetworkManager>
    {
        private NetworkManager() { }

        public override void OnSingletonInit()
        {
            base.OnSingletonInit();

            _msgQueue = new Queue<JObject>();

            // 将回调的 Key 和 托管函数 对应起来
            CallbackFactory.RegistCallbacks();
            BroadcastFactory.RegistEvents();
        }

        public override void Dispose()
        {
            base.Dispose();

            Debug.Log("NetworkManager.Dispose()");
            _pclient?.disconnect();
        }

        private PomeloClient _pclient;          // 
        private Queue<JObject> _msgQueue;    // 消息队列(收到的)

        public string host { get; private set; }
        public int port { get; private set; }
        public string userID { get; private set; }

        /// <summary>
        /// 建立起一条新的连接
        /// </summary>
        public void InitClient(string host, int port, JObject user)
        {
            this.host = host;
            this.port = port;
            this.userID = user["uid"].ToString();

            _pclient = new PomeloClient();
            _pclient.NetWorkStateChangedEvent += (state) =>
            {
                Debug.Log("NetWorkStateChangedEvent: " + state);
            };

            _pclient.initClient(this.host, this.port, () =>
            {
                _pclient.connect(user, data =>
                {
                    //this.Request(Routes.CONNECTOR_LOGIN, user);
                    ConnectorSender.reqLogin(user);
                });

                // 将广播事件的名称都注册到pomelo中
                foreach (KeyValuePair<string, Action<JObject>> pair in BroadcastFactory.Callbacks)
                {
                    RegistBroadcast(pair.Key);
                }
            });
        }

        /// <summary>
        /// 向服务器发通知,无响应
        /// </summary>
        /// <param name="route"></param>
        /// <param name="message"></param>
        public void Notify(string route, JObject message)
        {
            _pclient.notify(route, message);
        }

        /// <summary>
        /// 向服务器发请求,有响应
        /// </summary>
        /// <param name="route"></param>
        /// <param name="message"></param>
        public void Request(string route, JObject message)
        {
            _pclient.request(route, message, (data) =>
            {
                data[CallbackFactory.ROUTE_KEY_NAME] = route;
                _msgQueue.Enqueue(data);
            });
        }

        /// <summary>
        /// 注册了 广播事件的 处理逻辑
        /// </summary>
        /// <param name="eventName"></param>
        public void RegistBroadcast(string eventName)
        {
            _pclient.on(eventName, (data) =>
            {
                data[CallbackFactory.ROUTE_KEY_NAME] = eventName;
                data[BroadcastFactory.IS_EVT_KEY_NAME] = true; // 表示它是一个 广播事件
                _msgQueue.Enqueue(data);
            });
        }

        /// <summary>
        /// 处理消息队列
        /// </summary>
        public void Update()
        {
            while (_msgQueue.Count > 0)
            {
                JObject data = _msgQueue.Dequeue();
                string route = data[CallbackFactory.ROUTE_KEY_NAME].ToString();
                if (string.IsNullOrEmpty(route))
                {
                    Debug.LogError("cannt find route in msg");
                }

                // 调用回调函数
                if (!data.ContainsKey(BroadcastFactory.IS_EVT_KEY_NAME))
                {
                    // 非广播
                    CallbackFactory.InvokeHandle(route, data);
                }
                else
                {
                    BroadcastFactory.InvokeHandle(route, data);
                }
            }
        }
    }
}